﻿//-----------------------------------------------------------------------
// <copyright file="CustomerViewModel.cs" company="FER">
//     Copyright (c) All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace NMBP.ViewModels
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Windows.Media.Imaging;

    using GalaSoft.MvvmLight;
    using GalaSoft.MvvmLight.Command;
    using GalaSoft.MvvmLight.Messaging;

    using NMBP.DAL;
    using NMBP.Models;
    using NMBP.Models.Converters;
    using NMBP.ViewModels.Dialogs;

    /// <summary>
    /// This class contains properties that the customer View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// You can also use Blend to data bind with the tool's support.
    /// </para>
    /// <para>
    /// See http://www.galasoft.ch/mvvm/getstarted
    /// </para>
    /// </summary>
    public class CustomerViewModel : ViewModelBase
    {
        #region Bindable fields

        /// <summary>
        /// List of available products
        /// </summary>
        private ObservableCollection<Product> catalog;

        /// <summary>
        /// List of products in cart
        /// </summary>
        private ObservableCollection<Product> productsInCart;

        /// <summary>
        /// Selected product in catalog or cart
        /// </summary>
        private Product selectedProduct;

        /// <summary>
        /// Logged in person
        /// </summary>
        private Customer loggedInCustomer;

        /// <summary>
        /// Cart for current user and shopping
        /// </summary>
        private Cart cart;

        /// <summary>
        /// Selected products image
        /// </summary>
        private BitmapImage selectedProductImage;

        /// <summary>
        /// Selected product in cart view
        /// </summary>
        private Product selectedCartProduct;

        /// <summary>
        /// Action raised when customer view model needs to be initialized
        /// </summary>
        private Action<Customer> initCustomerViewModel;
        #endregion

        /// <summary>
        /// Initializes a new instance of the CustomerViewModel class
        /// </summary>
        public CustomerViewModel()
        {
            this.DialogService = new DialogService();
            this.initCustomerViewModel = new Action<Customer>(this.InitializeViewModel);
            Messenger.Default.Register<Customer>(this, "InitializeCustomerwindow", this.initCustomerViewModel);

            this.AddToCart = new RelayCommand(
                () =>
                    {
                        if (this.SelectedProduct != null)
                        {
                            if (this.SelectedProduct.Availability != Models.Enums.ProductAvailability.NotAvailable)
                            {
                                this.SelectedProduct.InCart = true;
                                this.Cart.AddProductToCart(this.SelectedProduct);
                                this.ProductsInCart.Add(this.SelectedProduct);
                            }
                            else
                            {
                                this.DialogService.ShowMessage("Nažalost proizvod trenutno nije dostupan, pa nije dodan u košaricu. :(", MessageType.INFO);
                            }
                        }
                        else
                        {
                            this.DialogService.ShowMessage("Nije označena stavka!", MessageType.ERROR);
                        }
                    });

            this.RemoveFromCart = new RelayCommand(
                () =>
                    {
                        if (this.SelectedCartProduct != null)
                        {
                            this.Cart.RemoveProductFromCart(this.SelectedCartProduct);
                            this.ProductsInCart.Remove(this.SelectedCartProduct);
                        }
                        else
                        {
                            this.DialogService.ShowMessage("Nije označena stavka!", MessageType.ERROR);
                        }
                    });

            this.SaveAndExit = new RelayCommand(
                () =>
                    {
                        if (this.Cart.Products.Count != 0)
                        {
                            this.DbFacade.SaveCart(this.Cart);
                        }

                        Messenger.Default.Send(1L, "CloseCustomerWindow");
                    });

            this.EditCustomer = new RelayCommand(
                () =>
                    {
                        Messenger.Default.Send(this.LoggedInCustomer, "OpenEditCustomerWindow");
                    });

            this.BuyItems = new RelayCommand(
                () =>
                    {
                        Messenger.Default.Send(this.Cart, "OpenCartPurchaseWindow");
                    });
        }

        #region Bindable properties

        /// <summary>
        /// Gets or sets dialog service
        /// </summary>
        public IDialogService DialogService { get; set; }

        /// <summary>
        /// Gets or sets db facade
        /// </summary>
        public DbFacade DbFacade { get; set; }

        /// <summary>
        /// Gets or sets List of available products
        /// </summary>
        public ObservableCollection<Product> Catalog
        {
            get
            {
                return this.catalog;
            }

            set
            {
                this.catalog = value;
                this.RaisePropertyChanged("Catalog");
            }
        }

        /// <summary>
        /// Gets or sets Selected product in catalog or cart
        /// </summary>
        public Product SelectedProduct
        {
            get
            {
                return this.selectedProduct;
            }

            set
            {
                this.selectedProduct = value;
                this.SelectedProductImage = value != null ? MyImageConverter.ConvertToBitmapImage(value.Image) : null;
                this.RaisePropertyChanged("SelectedProduct");
            }
        }

        /// <summary>
        /// Gets or sets Selected product in cart view
        /// </summary>
        public Product SelectedCartProduct
        {
            get
            {
                return this.selectedCartProduct;
            }

            set
            {
                this.selectedCartProduct = value;
                this.SelectedProductImage = value != null ? MyImageConverter.ConvertToBitmapImage(value.Image) : null;
                this.RaisePropertyChanged("SelectedCartProduct");
            }
        }

        /// <summary>
        /// Gets or sets Logged in person
        /// </summary>
        public Customer LoggedInCustomer
        {
            get
            {
                return this.loggedInCustomer;
            }

            set
            {
                this.loggedInCustomer = value;
                this.RaisePropertyChanged("LoggedInCustomer");
            }
        }

        /// <summary>
        /// Gets or sets Cart for current user and shopping
        /// </summary>
        public Cart Cart
        {
            get
            {
                return this.cart;
            }

            set
            {
                this.cart = value;
                this.RaisePropertyChanged("Cart");
            }
        }

        /// <summary>
        /// Gets or sets Selected products image
        /// </summary>
        public BitmapImage SelectedProductImage
        {
            get
            {
                return this.selectedProductImage;
            }

            set
            {
                this.selectedProductImage = value;
                this.RaisePropertyChanged("SelectedProductImage");
            }
        }

        /// <summary>
        /// Gets or sets List of products in cart
        /// </summary>
        public ObservableCollection<Product> ProductsInCart
        {
            get
            {
                return this.productsInCart;
            }

            set
            {
                this.productsInCart = value;
                this.RaisePropertyChanged("ProductsInCart");
            }
        }

        #endregion

        #region Bindable Commands
        /// <summary>
        /// Gets command raised when add to cart button is clicked
        /// </summary>
        public RelayCommand AddToCart { get; private set; }

        /// <summary>
        /// Gets command raised when remove from card button is clicked
        /// </summary>
        public RelayCommand RemoveFromCart { get; private set; }

        /// <summary>
        /// Gets a command raised when save and exit button is clicked
        /// </summary>
        public RelayCommand SaveAndExit { get; private set; }

        /// <summary>
        /// Gets a command raised when buy items button is clicked
        /// </summary>
        public RelayCommand BuyItems { get; private set; }

        /// <summary>
        /// Gets a command raised when edit customer button is clicked
        /// </summary>
        public RelayCommand EditCustomer { get; private set; }

        #endregion

        /// <summary>
        /// Initializes view model
        /// </summary>
        /// <param name="customer">customer for initialization</param>
        private void InitializeViewModel(Customer customer)
        {
            if (this.DbFacade == null)
            {
                this.DbFacade = new DbFacade();
            }

            this.LoggedInCustomer = customer;
            var products = this.DbFacade.GetProducts();

            this.Catalog = new ObservableCollection<Product>();
            foreach (var product in products)
            {
                this.Catalog.Add(product);
            }

            this.ProductsInCart = new ObservableCollection<Product>();

            Cart unorderedCart = this.DbFacade.GetCustomerUnorderedCart(this.LoggedInCustomer);
            if (unorderedCart != null)
            {
                this.Cart = unorderedCart;
                foreach (var product in this.Cart.Products)
                {
                    this.ProductsInCart.Add(product);
                }
            }
            else
            {
                this.Cart = new Cart()
                    {
                        Customer = this.LoggedInCustomer,
                        PaymentMethod = Models.Enums.PaymentMethod.Card,
                        Products = new List<Product>(),
                        TotalPrice = 0
                    };
            }
        }
    }
}
